<html><head><meta charset="utf-8"/><title>stream</title></head><body><h1>stream</h1><div class="x-wiki-content x-main-content">
 <p>
  <code>
   stream
  </code>
  是Node.js提供的又一个仅在服务区端可用的模块，目的是支持“流”这种数据结构。
 </p>
 <p>
  什么是流？流是一种抽象的数据结构。想象水流，当在水管中流动时，就可以从某个地方（例如自来水厂）源源不断地到达另一个地方（比如你家的洗手池）。我们也可以把数据看成是数据流，比如你敲键盘的时候，就可以把每个字符依次连起来，看成字符流。这个流是从键盘输入到应用程序，实际上它还对应着一个名字：标准输入流（stdin）。
 </p>
 <p>
  如果应用程序把字符一个一个输出到显示器上，这也可以看成是一个流，这个流也有名字：标准输出流（stdout）。流的特点是数据是有序的，而且必须依次读取，或者依次写入，不能像Array那样随机定位。
 </p>
 <p>
  <img alt="nodejs-stream" data-src="/files/attachments/1056921912079200/l" src="https://www.liaoxuefeng.com/files/attachments/1056921912079200/l"/>
 </p>
 <p>
  有些流用来读取数据，比如从文件读取数据时，可以打开一个文件流，然后从文件流中不断地读取数据。有些流用来写入数据，比如向文件写入数据时，只需要把数据不断地往文件流中写进去就可以了。
 </p>
 <p>
  在Node.js中，流也是一个对象，我们只需要响应流的事件就可以了：
  <code>
   data
  </code>
  事件表示流的数据已经可以读取了，
  <code>
   end
  </code>
  事件表示这个流已经到末尾了，没有数据可以读取了，
  <code>
   error
  </code>
  事件表示出错了。
 </p>
 <p>
  下面是一个从文件流读取文本内容的示例：
 </p>
 <pre><code>'use strict';

var fs = require('fs');

// 打开一个流:
var rs = fs.createReadStream('sample.txt', 'utf-8');

rs.on('data', function (chunk) {
    console.log('DATA:')
    console.log(chunk);
});

rs.on('end', function () {
    console.log('END');
});

rs.on('error', function (err) {
    console.log('ERROR: ' + err);
});
</code></pre>
 <p>
  要注意，
  <code>
   data
  </code>
  事件可能会有多次，每次传递的
  <code>
   chunk
  </code>
  是流的一部分数据。
 </p>
 <p>
  要以流的形式写入文件，只需要不断调用
  <code>
   write()
  </code>
  方法，最后以
  <code>
   end()
  </code>
  结束：
 </p>
 <pre><code>'use strict';

var fs = require('fs');

var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
ws1.write('使用Stream写入文本数据...\n');
ws1.write('END.');
ws1.end();

var ws2 = fs.createWriteStream('output2.txt');
ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8'));
ws2.write(new Buffer('END.', 'utf-8'));
ws2.end();
</code></pre>
 <p>
  所有可以读取数据的流都继承自
  <code>
   stream.Readable
  </code>
  ，所有可以写入的流都继承自
  <code>
   stream.Writable
  </code>
  。
 </p>
 <h3>
  pipe
 </h3>
 <p>
  就像可以把两个水管串成一个更长的水管一样，两个流也可以串起来。一个
  <code>
   Readable
  </code>
  流和一个
  <code>
   Writable
  </code>
  流串起来后，所有的数据自动从
  <code>
   Readable
  </code>
  流进入
  <code>
   Writable
  </code>
  流，这种操作叫
  <code>
   pipe
  </code>
  。
 </p>
 <p>
  在Node.js中，
  <code>
   Readable
  </code>
  流有一个
  <code>
   pipe()
  </code>
  方法，就是用来干这件事的。
 </p>
 <p>
  让我们用
  <code>
   pipe()
  </code>
  把一个文件流和另一个文件流串起来，这样源文件的所有数据就自动写入到目标文件里了，所以，这实际上是一个复制文件的程序：
 </p>
 <pre><code>'use strict';

var fs = require('fs');

var rs = fs.createReadStream('sample.txt');
var ws = fs.createWriteStream('copied.txt');

rs.pipe(ws);
</code></pre>
 <p>
  默认情况下，当
  <code>
   Readable
  </code>
  流的数据读取完毕，
  <code>
   end
  </code>
  事件触发后，将自动关闭
  <code>
   Writable
  </code>
  流。如果我们不希望自动关闭
  <code>
   Writable
  </code>
  流，需要传入参数：
 </p>
 <pre><code>readable.pipe(writable, { end: false });
</code></pre>
 <h3>
  参考源码
 </h3>
 <p>
  <a href="https://github.com/michaelliao/learn-javascript/tree/master/samples/node/stream">
   stream
  </a>
 </p>
</div>
</body></html>